
const { ccclass, property } = cc._decorator;
import baseManager from "../../../app/base/baseManager";
import { app } from "../../../app/app";
import * as sdk from '../../../script/sdk/sdk'

interface clipVideoOptions {
    path: string,
    timeRange?: [number, number],
    clipRange?: [number, number],
    success?: (videoPath: string) => void,
    fail?: Function,
    complete?: Function
}

interface recordClipOptions {
    timeRange?: [number, number],
    success?: (index: number) => void,
    fail?: Function,
    complete?: Function
}

@ccclass
export default class recorderManager extends baseManager {
    private time = 0;
    private videoUrl = '';
    private isrecoding = false;

    private startCB: Function = null;
    private pauseCB: Function = null;
    private resumeCB: Function = null;
    private stopCB: Function = null;
    private errorCB: Function = null;

    private loop: boolean = true;
    private autoStop: boolean = true;

    private clipIndexList: number[] = []; // 剪辑索引列表

    public getVideoUrl() {
        return this.videoUrl;
    }

    public getVideoTime() {
        return this.time;
    }

    /**
     * @param startCB 
     * @param loop  循环覆盖
     */
    public begin(startCB?: Function, errorCB?: Function, loop: boolean = true) {
        this.unscheduleAllCallbacks();

        if (this.isrecoding) {
            return startCB && startCB('已经在录屏了');
        }

        this.startCB = startCB;
        this.errorCB = errorCB;

        this.time = 0;
        this.loop = loop;
        this.videoUrl = '';
        this.autoStop = true;
        this.isrecoding = false;
        this.clipIndexList.length = 0;

        //@ts-ignore
        // 字节平台暂时在开发者工具下不执行录屏操作(因为开发者工具有BUG)
        if (sdk.systemInfo.platform === 'devtools') return;

        sdk.recorder.start({
            onStart: () => {
                this.log('start');
                this.isrecoding = true;
                if (this.startCB) {
                    this.startCB();
                    this.startCB = null;
                }
            },
            onPause: () => {
                this.log('pause');
                this.isrecoding = false;
                if (this.pauseCB) {
                    this.pauseCB();
                    this.pauseCB = null;
                }
            },
            onResume: () => {
                this.log('resume');
                this.isrecoding = true;
                if (this.resumeCB) {
                    this.resumeCB();
                    this.resumeCB = null;
                }
            },
            onStop: (url) => {
                const task = app.lib.task.createSync();

                if ((this.autoStop && this.loop) || this.time <= 20) {
                    task.add((next) => {
                        this.isrecoding = false;
                        this.videoUrl = url || '';
                        next();
                    })
                } else if (this.clipIndexList.length > 0) {
                    task.add((next) => {
                        this.clipVideo({
                            path: url,
                            success: (videoPath) => {
                                this.videoUrl = videoPath || url || '';
                            },
                            fail: () => {
                                this.videoUrl = url || '';
                            },
                            complete: () => {
                                this.isrecoding = false;
                                next();
                            }
                        })
                    })
                } else {
                    task.add((next) => {
                        this.clipVideo({
                            path: url,
                            timeRange: [20, 0],
                            success: (videoPath) => {
                                this.videoUrl = videoPath || url || '';
                            },
                            fail: () => {
                                this.videoUrl = url || '';
                            },
                            complete: () => {
                                this.isrecoding = false;
                                next();
                            }
                        })
                    })
                }

                task.start(() => {
                    this.log('stop', url, this.videoUrl, this.autoStop, this.loop, this.time);
                    if (this.autoStop) {
                        if (!this.loop) return;
                        this.scheduleOnce(function () {
                            this.log('loop');
                            this.begin(null, this.errorCB, this.loop);
                        }, 1);
                    } else if (this.stopCB) {
                        this.stopCB(this.videoUrl, this.time);
                        this.stopCB = null;
                    }
                })
            },
            onError: () => {
                this.log('error');
                this.isrecoding = false;
                if (this.errorCB) {
                    this.errorCB();
                    this.errorCB = null;
                } else if (this.loop) {
                    this.scheduleOnce(function () {
                        this.log('loop');
                        this.begin(this.startCB, this.errorCB, this.loop);
                    }, 1);
                }
            }
        }, 100);
    }

    public pause(pauseCB?: Function) {
        this.pauseCB = pauseCB;
        sdk.recorder.pause();
    }

    public resume(resumeCB?: Function) {
        this.resumeCB = resumeCB;
        sdk.recorder.resume();
    }

    /**
     * 停止录屏，不足5秒会延迟到5秒后停止
     * @param stopCB 
     * @param force  强制停止
     */
    public stop(stopCB?: (url: string, time: number) => void, force = false) {
        this.unscheduleAllCallbacks();
        this.autoStop = false;
        this.stopCB = stopCB;
        if (force === false && this.time < 5) {
            this.scheduleOnce(function () {
                sdk.recorder.stop();
            }, 5 - this.time);
        } else {
            sdk.recorder.stop();
        }
    }

    /**
     * 记录精彩的视频片段，调用时必须是正在录屏，
     * 以调用时的录屏时刻为基准，指定前 x 秒，后 y 秒为将要裁剪的片段，可以多次调用，记录不同时刻。
     * 在结束录屏时，可以调用 clipVideo 接口剪辑并合成记录的片段。
     * @param options 
     * options.timeRange 默认[3, 3]
     */
    public recordClip(options: recordClipOptions) {
        const timeRange = options.timeRange || [3, 3];
        const success = options.success;
        const fail = options.fail;
        const complete = options.complete;

        return sdk.recorder.recordClip({
            timeRange,
            success: (res) => {
                this.log('recordClip', res);
                this.clipIndexList.push(res.index);
                success && success(res.index);
            },
            fail: (res) => {
                this.log('recordClip', 'fail', res);
                fail && fail();
            },
            complete
        });
    }

    /**
     * 剪辑精彩的视频片段。
     * @param options 
     */
    public clipVideo(options: clipVideoOptions) {
        const path = options.path;
        const timeRange = options.timeRange;
        const clipRange = options.clipRange;
        const success = options.success;
        const fail = options.fail;
        const complete = options.complete;

        return sdk.recorder.clipVideo({
            path,
            timeRange,
            clipRange,
            success: (res) => {
                this.log('clipVideo', res);
                success && success(res.videoPath);
            },
            fail: (res) => {
                this.log('clipVideo', 'fail', res);
                fail && fail();
            },
            complete
        });
    }

    public update(dt: number) {
        if (this.isrecoding) {
            this.time += dt;
        }
    }
};